package com.pan.service.impl;

import com.pan.dao.AdminDao;
import com.pan.dao.AdminTableSelectDao;
import com.pan.dao.AdminTableUpdateDao;
import com.pan.entity.Admin;
import com.pan.entity.Result;
import com.pan.enume.ResultEnum;
import com.pan.service.AdminService;
import com.pan.tools.*;
import com.pan.vo.AdminRegisterVo;
import com.pan.vo.AdminVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;


@Service("adminService")
public class AdminServiceImpl implements AdminService {

    @Resource
    private RedisTools redisTools;
    @Resource
    private AdminTableSelectDao adminTableSelectDao;
    @Resource
    private AdminTableUpdateDao adminTableUpdateDao;
    @Resource
    private AdminDao adminDao;
    @Override
    @Transactional
    public Result register(String adminTicket, AdminRegisterVo adminRegisterVo){
        Result result_id = redisTools.hget("admin:"+adminTicket,"id");
        Long createAdminId = (Long) result_id.getData();
        if (result_id.getCode()!=200||createAdminId==null){
            return new Result(ResultEnum.USER_NOT_FOUND_ERROR);
        }
        Admin isAdmin = adminTableSelectDao.selectByTel(adminRegisterVo.getTel());
        if (isAdmin!=null){
            return new Result(403,"该用户已存在");
        }
        String salt = SaltTools.getSalt(6);
        String passAddSalt = MD5Tools.fromPassToDBPass(adminRegisterVo.getPassword(),salt);
        Admin admin = new Admin(adminRegisterVo,passAddSalt,salt, createAdminId);
        Long id = adminDao.insert(admin);
        return new Result(ResultEnum.SUCCESS,id);
    }
    @Override
    public Result toLogin(HttpServletRequest request, HttpServletResponse response, Long tel, String password){
        Result<String> loginResult = login(tel,password);
        if (loginResult.getCode()!=200){
            return loginResult;
        }
        String adminTicket = loginResult.getData();
        Cookie cookie = CookieTools.getCookie(request,"adminTicket",adminTicket);
        response.addCookie(cookie);
        return loginResult;
    }
    @Transactional
    @Override
    public Result<String> login(Long tel,String password){
        Admin admin= adminTableSelectDao.selectByTel(tel);
        if (admin==null || admin.getAdminStatus() == 1){
            return new Result(ResultEnum.USER_NOT_FOUND_ERROR);
        }
        String salt = admin.getSalt();
        String passAddSalt = MD5Tools.fromPassToDBPass(password,salt);
        if (!passAddSalt.equals(admin.getPassword())){
            return new Result(ResultEnum.PASSWORD_ERROR);
        }
        Timestamp nowTime = new Timestamp(System.currentTimeMillis());
        Long loginCount = admin.getLoginCount();
        adminTableUpdateDao.updateLoginCount(admin.getId(), loginCount);
        adminTableUpdateDao.updateLastLoginDate(admin.getId(), nowTime);
        admin.setLoginCount(loginCount);
        admin.setLastLoginDate(nowTime);

        String adminTicket = UUIDTools.getUUID();
        Map<String,Object> map = ObjectToMap.toMap(admin);
        redisTools.hset("admin:"+adminTicket,map);
        redisTools.expire("admin:"+adminTicket,7L);
        Result<String> result =  new Result(ResultEnum.SUCCESS,adminTicket);
        return result;
    }
    @Override
    public Result<AdminVo> selectByTel(String adminTicket, Long tel){
        Result isResult = redisTools.hget("admin:"+adminTicket,"id");
        if (isResult.getCode()==200||isResult.getData()==null){
            return new Result<>(ResultEnum.NOT_LOGIN_ERROR);
        }
        Admin admin = adminTableSelectDao.selectByTel(tel);
        if (admin==null){
            return new Result<>(ResultEnum.SUCCESS);
        }
        AdminVo adminVo = new AdminVo(admin);
        Result<AdminVo> result = new Result<>(ResultEnum.SUCCESS,adminVo);
        return result;
    }
    @Transactional
    @Override
    public Result updatePassword(String adminTicket, String oldPassword, String newPassword) throws NoSuchFieldException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        Result idResult = redisTools.hget("admin:"+adminTicket,"id");
        Long id = (Long) idResult.getData();
        if (idResult.getCode()!=200||id==null){
            return new Result(ResultEnum.NOT_LOGIN_ERROR);
        }
        Admin admin = adminTableSelectDao.selectById(id);
        String oldSalt = admin.getSalt();
        String oldPasswordAddSalt =  MD5Tools.fromPassToDBPass(oldPassword,oldSalt);
        if (!oldPasswordAddSalt.equals(admin.getPassword())){
            return new Result(ResultEnum.PASSWORD_ERROR);
        }
        String newSalt = SaltTools.getSalt(6);
        String newPasswordAddSalt = MD5Tools.fromPassToDBPass(newPassword,newSalt);
        updateInfo(adminTicket,"password",newPasswordAddSalt);
        updateInfo(adminTicket,"salt",newSalt);
        Map<String,Object> map = new HashMap();
        map.put("password",newPasswordAddSalt);
        map.put("salt",newSalt);
        redisTools.hset("admin:"+adminTicket,map);
        return new Result(ResultEnum.SUCCESS);
    }
    @Override
    @Transactional
    public Result updateInfo(String adminTicket, String memberName, Object value) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Result adminResult = redisTools.hget("admin:"+adminTicket,"id");
        Long id = (Long) adminResult.getData();
        if (adminResult.getCode()!=200||id==null){
            return new Result(ResultEnum.NOT_LOGIN_ERROR);
        }
        Field field = Admin.class.getDeclaredField(memberName);
        if (field==null){
            return new Result(ResultEnum.NOT_FOUND_ERROR);
        }
        Class memberType = field.getType();

        String firstUp = memberName.substring(0,1).toUpperCase()+memberName.substring(1);
        String methodName = "update"+firstUp;
        Method method = AdminTableUpdateDao.class.getMethod(methodName,Long.class,memberType);
        method.invoke(adminTableUpdateDao,id,value);
        return new Result(ResultEnum.SUCCESS);
    }
    @Override
    public Result logoff(HttpServletResponse response, String adminTicket){
        Cookie cookie = new Cookie("adminTicket","");
        cookie.setMaxAge(-1);
        cookie.setPath("/");
        response.addCookie(cookie);
        redisTools.del("admin:"+adminTicket);
        return new Result(ResultEnum.SUCCESS);
    }
}
